import pygame
import sys
import time
from settings import Settings
from player import Player
from bullet import PlayerBullet
from alien import NormalAlien
from game_stats import GameStat


class AlienInvasion:
    def __init__(self):
        pygame.init()  # init background setting
        self.settings = Settings()
        self.stat = GameStat()
        self.screen = pygame.display.set_mode((self.settings.screen_height, self.settings.screen_width))  # , self.settings.screen_mode
        self.screen_rect = self.screen.get_rect()
        pygame.display.set_caption('Alien Invasion')  # init window title
        self.player = Player(self)
        self.aliens = pygame.sprite.Group()
        self.bullets = pygame.sprite.Group()
        self._aliens_create()  # create the first wave of aliens

    # menu
    def _menu_event_check(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    self.stat.game_active = True
                elif event.key == pygame.K_ESCAPE:
                    sys.exit()

    def _menu_screen_update(self):
        if self.stat.game_active is False:
            bg_img = pygame.image.load('_image/bg_StartMenu.png')
            self.screen.blit(bg_img, (0, 0))

    def _game_event_check_KEYDOWN(self, event):
        # check key press
        if event.key == pygame.K_w:
            self.player.move_up = True
        if event.key == pygame.K_a:
            self.player.move_left = True
        if event.key == pygame.K_s:
            self.player.move_down = True
        if event.key == pygame.K_d:
            self.player.move_right = True

    def _game_event_check_KEYUP(self, event):
        # check key release
        if event.key == pygame.K_w:
            self.player.move_up = False
        if event.key == pygame.K_a:
            self.player.move_left = False
        if event.key == pygame.K_s:
            self.player.move_down = False
        if event.key == pygame.K_d:
            self.player.move_right = False
        if event.key == pygame.K_ESCAPE:
            sys.exit()

    def _game_event_check(self):
        for event in pygame.event.get():  # monitor events from mouse and keyboard
            # check QUIT
            if event.type == pygame.QUIT:
                sys.exit()
            # check keyboard WASD
            elif event.type == pygame.KEYDOWN:
                self._game_event_check_KEYDOWN(event)
            elif event.type == pygame.KEYUP:
                self._game_event_check_KEYUP(event)
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    self.settings.fire = True
                if event.button == 3:
                    pass  # boom
            elif event.type == pygame.MOUSEBUTTONUP:
                if event.button == 1:
                    self.settings.fire = False

    # bullets
    def _bullets_fire(self):
        current_time = time.time()
        if current_time - self.stat.last_fire_time >= self.settings.fire_speed:
            new_bullet = PlayerBullet(self)
            self.bullets.add(new_bullet)
            self.stat.last_fire_time = current_time

    def _bullets_update(self):
        self.bullets.update()
        for bullet in self.bullets.copy():
            if bullet.rect.bottom <= self.screen_rect.top:
                self.bullets.remove(bullet)

    # player
    def _player_check_collision_with_bullets(self):
        if pygame.sprite.spritecollide(self.player, self.aliens, False):
            self._player_attacked()

    def _player_attacked(self):
        self.player.health -= 1
        if self.player.health <= 0:
            pass
        else:
            time.sleep(0.5)
            self.aliens.empty()
            self.bullets.empty()

    # aliens
    def _aliens_create(self):
        if self.settings.create_normal is True:
            for i in range(self.settings.rows):
                for j in range(self.settings.max_normal // self.settings.rows):
                    alien = NormalAlien(self, i, j)
                    self.aliens.add(alien)

    def _alien_check_collision_with_bullets(self):
        attacked_aliens = pygame.sprite.groupcollide(self.aliens, self.bullets, False, True)
        for alien in attacked_aliens.keys():
            alien: NormalAlien
            alien.health -= 1

    def _aliens_update(self):
        self.aliens.update()
        self._alien_check_collision_with_bullets()
        flag_break = False
        for alien in self.aliens.copy():
            alien: NormalAlien
            # Dead
            if alien.health <= 0:
                self.aliens.remove(alien)
            # leave out of screen
            if alien.rect.top >= self.screen_rect.bottom \
                    or alien.health == 0:
                self.aliens.remove(alien)
            # touch edges
            if alien.check_edges() is True:
                flag_break = True
        for alien in self.aliens.copy():
            alien: NormalAlien
            if flag_break is True:
                alien.horizontal_direction *= -1

    def _screen_update(self):
        # update basic screen
        self.screen.fill(self.settings.bg_color)  # set background color
        if self.stat.game_active is True:
            bg_img = pygame.image.load('_image/bg_01.jpg')
            self.screen.blit(bg_img, (0, 0))
        # update bullets
        if self.settings.fire is True:
            self._bullets_fire()
        for bullet in self.bullets.sprites():
            bullet.draw()
        # update player
        self.player.blit()
        # update aliens
        self.aliens.draw(self.screen)
        pygame.display.flip()  # show current painted screen

    def _game_over(self):
        # print 'Game Over' to screen
        # collect score
        # back to start menu
        self.stat.game_active = False

    def run(self):
        while True:
            if self.stat.game_active is True:
                self._game_event_check()
                self._bullets_update()
                self.player.update()
                self._aliens_update()
                self._screen_update()
            else:
                self._menu_event_check()


if __name__ == '__main__':
    game = AlienInvasion()
    game.run()
